package cn.dianchiyun.protocol.netty.dtu.car;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

public class SmartCarDecoder extends ByteToMessageDecoder {
 
	/**
	 * <pre>
	 * 协议开始的标准head_data，int类型，占据4个字节.
	 * 表示数据的长度contentLength，int类型，占据4个字节.
	 * </pre>
	 */
	public final int BASE_LENGTH = 7;
 
	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf buffer,
						  List<Object> out) throws Exception {
		// 可读长度必须大于基本长度
		if (buffer.readableBytes() >= BASE_LENGTH) {
			// 防止socket字节流攻击
			// 防止，客户端传来的数据过大
			// 因为，太大的数据，是不合理的
			if (buffer.readableBytes() > 2048) {
				buffer.skipBytes(buffer.readableBytes());
			}
 
			// 记录包头开始的index
			int beginReader;
 
			while (true) {
				// 获取包头开始的index
				beginReader = buffer.readerIndex();
				// 标记包头开始的index
				buffer.markReaderIndex();
				// 读到了协议的开始标志，结束while循环
				if (buffer.readInt() == 0x7E) {
					break;
				}
 
				// 未读到包头，略过一个字节
				// 每次略过，一个字节，去读取，包头信息的开始标记
				buffer.resetReaderIndex();
				buffer.readByte();
 
				// 当略过，一个字节之后，
				// 数据包的长度，又变得不满足
				// 此时，应该结束。等待后面的数据到达
				if (buffer.readableBytes() < BASE_LENGTH) {
					return;
				}
			}
 
			// 消息的长度
 
			int length = buffer.readInt();
			// 判断请求数据包数据是否到齐
			if (buffer.readableBytes() < length) {
				// 还原读指针
				buffer.readerIndex(beginReader);
				return;
			}
 
			// 读取data数据
			byte[] data = new byte[length];
			buffer.readBytes(data);

			StringBuilder hex = new StringBuilder(2 * data.length);
			String HEXES = "0123456789ABCDEF";
			for (int i = 0; i < data.length; i++) {
				byte b = data[i];
				hex.append(HEXES.charAt((b & 0xF0) >> 4))
						.append(HEXES.charAt((b & 0x0F)));
			}
			out.add(hex.toString());
		}
	}
 
}